package mya_dc.compilation_server.compilation;

import java.net.Socket;
import mya_dc.shared_classes.CompilationErrors;
import mya_dc.shared_classes.ConnectInfo;
import mya_dc.shared_classes.MYA_File;
import mya_dc.shared_classes.Message;
import mya_dc.shared_classes.SharedDefinitions;
import mya_dc.shared_classes.Transmitter;
import mya_dc.shared_classes.Message.EMessageType;

/**
 * Handles the connection between one Slave.
 * <ul>
 * <li>Connects to slave
 * <li>Sends him all files in "m_packDir"
 * <li>Accepts result object file to "m_binDir" and errors
 * <li>Sets errors at parent class
 * </ul>
 * 
 * @author Yuval Shimron
 * 	  <br> MYA
 *
 */
class CompilationThread extends Thread
{
	private boolean m_bAbortCompilation;
	private ConnectInfo m_slaveConnectInfo;
	private String m_packDir;
	private String m_binDir;
	private int m_iCounter;
	private ProjectBuilder m_ProjBuildClass;
		
	/**
	 * Constructor
	 * 
	 * @param slaveInetAddress
	 * @param packDir - Directory of files to compile
	 * @param binDir - Directory of output binary files (object files)
	 * @param iCounter - number of package
	 * @param ProjBuildClass - parent class
	 */
	public CompilationThread(
			ConnectInfo slaveInetAddress, 
			String packDir, 
			String binDir, 
			int iCounter, 
			ProjectBuilder ProjBuildClass)
	{
		m_slaveConnectInfo = slaveInetAddress;
		m_packDir = packDir;
		m_binDir = binDir;
		m_iCounter = iCounter;
		m_ProjBuildClass = ProjBuildClass;
		m_bAbortCompilation = false;
	}
	
	/**
	 * Marks compilation aborted notification
	 */
	public synchronized void abortCompilation()
	{
		m_bAbortCompilation = true;
	}
	
	/**
	 * Returns compilation aborted notification
	 */
	private synchronized boolean compilationAborted()
	{
		return m_bAbortCompilation;
	}
	
	public void run()
	{ 
		Transmitter slaveTrans;
		try {
			Socket slaveSktNum = new Socket(m_slaveConnectInfo.address,m_slaveConnectInfo.listenPort);
			slaveTrans = new Transmitter(slaveSktNum, 
					m_packDir+Integer.toString(m_iCounter), 
					SharedDefinitions.SecsBetweenTwoKeepAliveMessages);
			MYA_File packDir = new MYA_File(m_packDir+Integer.toString(m_iCounter));				
			MYA_File[] files = packDir.listFiles();
			
			slaveTrans.send(new Message(
							Message.EMessageType.LOGIN_ENTITY_IDENTIFICATION, 
							SharedDefinitions.Entity.ENTITY_COMPILATION));
			slaveTrans.send(new Message(Message.EMessageType.FILE_TRANSFER, files));
			slaveTrans.send(new Message(Message.EMessageType.FILE_TRANSFER_NO_MORE_FILES,m_ProjBuildClass.m_compFlags));
		}
		catch (Exception e)
		{
			// unexpected error. returning without marking done
			return;
		}	
		
		if (compilationAborted())
			return;
		
		try {
			// tries to get object files (or no object files message)
			Message resMessage = slaveTrans.receive();

			if ( resMessage.getType() == Message.EMessageType.COMPILATION_RESULT_ERRORS )
			{
				if (!compilationAborted()) 
				{
					// sets errors
					m_ProjBuildClass.setError(ProjectBuilder.ProjectBuilderErrors.errCompilationFailed);
					m_ProjBuildClass.addErrors((CompilationErrors)resMessage.getObject());
				}
			}
			else if ( resMessage.getType() != Message.EMessageType.COMPILATION_RESULT_NO_ERRORS )
			{
				// unexpected error. returning without marking done
				return;
			}
		}	
		catch (Exception e)
		{
			// unexpected error. returning without marking done
			return;
		}
		try {
			slaveTrans.setWorkingDirectory(m_binDir);
			Message resMessage = slaveTrans.receive();
			if ( resMessage.getType() != Message.EMessageType.FILE_TRANSFER_OBJECT_FILES &&
				 resMessage.getType() != Message.EMessageType.FILE_TRANSFER_NO_OBJECT_FILES	)
			{
				// unexpected error. returning without marking done
				return;
			}
			slaveTrans.send(new Message(EMessageType.SUCCESS,null));
		}
		catch (Exception e)
		{
			// unexpected error. returning without marking done
			return;
		}
		if (!compilationAborted()) 
		{
			m_ProjBuildClass.markDone(m_iCounter);
		}
		return;
	}
}

